package com.sr.recitewords.filter;

import com.alibaba.fastjson.JSON;
import com.sr.recitewords.common.vo.GeneralResult;
import com.sr.recitewords.exception.BizException;
import com.sr.recitewords.exception.CheckNotNullUtil;
import com.sr.recitewords.exception.GlobalExceptionHandler;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

/**
 * aop打印日志
 */
@Aspect
@Component
@Order(-1)
public class ProjectLogAspect {
    private static final Logger logger = LogManager.getLogger(ProjectLogAspect.class);

    // 以 controller包和TestController下定义的所有请求为切入点
    @Pointcut("execution(public * com.sr.recitewords.controller..*(..))")
    public void log() {
    }

    @Before("log()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
    }

    @After("log()")
    public void doAfter(JoinPoint joinPoint) throws Throwable {
    }

    /**
     * 环绕
     */
    @Around("log()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes == null) {
            return null;
        }
        HttpServletRequest request = attributes.getRequest();
        long startTime = System.currentTimeMillis();
        // start
        logger.info("========================[" + request.getMethod() + "] called url:" + request.getServletPath() + ", ip:" + request.getRemoteAddr());
        Object rsp = null;
        Object[] reqs = joinPoint.getArgs();
        for (int i = 0; reqs != null && i < reqs.length; i++) {
            Object req = reqs[i];
            if (req instanceof HttpServletRequest || req instanceof HttpServletResponse) {
            } else {
                String reqJson = JSON.toJSONString(req);
                reqJson = GlobalExceptionHandler.replaceAllImgBase64(reqJson);
                logger.info("请求入参参数：" + i + ".req:" + reqJson);
                //调用Util判断必选参数
                if (!CheckNotNullUtil.isRequiredNotNull(req)) {
                    //返回参数不符合信息,
                    rsp = GeneralResult.genErrorResult(parseErrorMsg(req, request), "666");
                }
                //集合操作
                if (req instanceof List) {
                    //遍历
                    for (Object o : (List) req) {
                        //调用Util判断必选参数
                        if (!CheckNotNullUtil.isRequiredNotNull(o)) {
                            rsp = GeneralResult.genErrorResult(parseErrorMsg(o, request), "666");
                            break;
                        }
                    }
                }
            }
        }
        try {
            if (rsp == null) {
                rsp = joinPoint.proceed();
            }
        } catch (BizException tmp) {
            // 在这里先处理一道业务异常，以免在全局异常中过多打印
            logger.info("tmp: " + tmp);
            rsp = GeneralResult.genErrorResult(tmp.getErrorMsg(), tmp.getErrorCode());
        }
        // end
        GlobalExceptionHandler.printRsp(rsp);
        long span = System.currentTimeMillis() - startTime;
        logger.info("span: " + span + " ms, on " + request.getServletPath());
        return rsp;
    }

    private String parseErrorMsg(Object o, HttpServletRequest request) {
        //返回参数不符合信息,
        String message = CheckNotNullUtil.getRequiredNotNullMsg(o);
        String err = "requestURI:" + request.getRequestURI() + ",errorCode:" + "666" + ",errorMsg:" + message;
        logger.error(err.replaceAll("\r\n", ""));
        return message;
    }

}
